home *** CD-ROM | disk | FTP | other *** search
/ ftp.hypersurf.com / ftp.hypersurf.com.tar / ftp.hypersurf.com / pub / mac / ftp / Fetch_3.0.3.hqx / Fetch 3.0.3 Installer / FetchAE.cp < prev    next >
Text File  |  1996-12-30  |  25KB  |  936 lines

  1. /*
  2.      FetchAE.cp -- sample Apple Event code for Fetch
  3.      
  4.      Copyright ⌐ 1996, Trustees of Dartmouth College
  5.      All Rights Reserved.
  6.      
  7.      Distribution and use of this code is hereby permitted, provided that any resulting
  8.      work includes the copyright statement above.
  9. */
  10.  
  11. #include <string.h>
  12.  
  13. #include <AEObjects.h>
  14. #include <AEPackObject.h>
  15.  
  16. #include "FetchAE.h"
  17.  
  18. static void InitDesc(AEDesc *desc);
  19. static void DisposeDesc(AEDesc *desc);
  20. static void CStringToDesc(char *valuep, DescType dType, AEDesc *desc);
  21. static void DescTypeToDesc(OSType value, DescType dType, AEDesc *desc);
  22. static void LongToDesc(long value, DescType dType, AEDesc *desc);
  23. static void FSSpecToDesc(FSSpec *valuep, DescType dType, AEDesc *desc);
  24. static Boolean findProcessBySignature(OSType sig, ProcessSerialNumber *psn_p, long *proc_mode_p);
  25. static Boolean findAppBySignature(OSType sig, FSSpec *fspec_p);
  26. static OSErr InitAEToApp(OSType appSig, AEEventClass eventClass, AEEventID eventID, 
  27.             AppleEvent *aevt, Boolean *running);
  28. static OSErr SendAEToApp(OSType appSig, AppleEvent *aevt, AppleEvent *aereply, AEIdleUPP idleUPP, Boolean running);
  29. static OSErr SendDirectAppleEvent(OSType appSig, AEEventClass eventClass, AEEventID eventID,
  30.                 AEDesc *directDesc, AppleEvent *aereply, AEIdleUPP idleUPP);
  31. static OSErr SendDirectAppleEventWithArg(OSType appSig, AEEventClass eventClass, AEEventID eventID,
  32.                 AEDesc *directDesc, AEKeyword argKey, AEDesc *argDesc,
  33.                 AppleEvent *aereply, AEIdleUPP idleUPP);
  34. static OSErr SendDirectAppleEventWithThreeArgs(OSType appSig, AEEventClass eventClass, AEEventID eventID,
  35.                 AEDesc *directDesc, AEKeyword argKey, AEDesc *argDesc,
  36.                 AEKeyword arg2Key, AEDesc *arg2Desc,
  37.                 AEKeyword arg3Key, AEDesc *arg3Desc,
  38.                 AppleEvent *aereply, AEIdleUPP idleUPP);
  39. static OSErr SendCreateAppleEvent(OSType appSig, DescType objClass, AEDesc *insertLocDesc,
  40.                 AEDesc *dataDesc, AEDesc *propDesc, 
  41.                 AppleEvent *aereply, AEIdleUPP idleUPP);
  42. static OSErr SendMoveCloneAppleEvent(OSType appSig, AEEventID eventID, AEDesc *directDesc, 
  43.                 AEDesc *insertLocDesc, AppleEvent *aereply, AEIdleUPP idleUPP);
  44. static OSErr CreateFormNameOSpec(char *name, DescType objClass, AEDesc *containerDesc, AEDesc *ospecDesc);
  45. static OSErr CreatePropertyOSpec(DescType propCode, AEDesc *containerDesc, AEDesc *ospecDesc);
  46.  
  47. /*
  48.  * InitDesc() --
  49.  *    Initialize a descriptor.
  50.  */
  51. void InitDesc(AEDesc *desc)
  52. {
  53.     desc->descriptorType = typeNull;
  54.     desc->dataHandle = nil;
  55. }
  56.  
  57. /*
  58.  * DisposeDesc() --
  59.  *    Dispose of descriptor data and mark descriptor as empty.
  60.  */
  61. void DisposeDesc(AEDesc *desc)
  62. {
  63.     if (desc->dataHandle != nil)
  64.         (void) AEDisposeDesc(desc);
  65.     InitDesc(desc);
  66. }
  67.  
  68. /*
  69.  * CStringToDesc() -- 
  70.  *    Put a C string into a descriptor record.
  71.  */
  72. void CStringToDesc(char *valuep, DescType dType, AEDesc *desc)
  73. {
  74.     desc->descriptorType = dType;
  75.     if (dType == typeChar)
  76.         (void) PtrToHand(valuep, &desc->dataHandle, strlen(valuep));
  77.     else if (dType == typeIntlText)
  78.     {
  79.         desc->dataHandle = NewHandle(4+valuep[0]);
  80.         *(short *) *desc->dataHandle = smRoman;
  81.         *(short *) (*desc->dataHandle + 2) = langEnglish;
  82.         BlockMoveData(valuep, *desc->dataHandle + 4, strlen(valuep));
  83.     }
  84.     else
  85.         InitDesc(desc);
  86. } /* CStringToDesc() */
  87.  
  88. /*
  89.  * DescTypeToDesc() -- 
  90.  *    Put an OSType into a descriptor record.
  91.  */
  92. void DescTypeToDesc(OSType value, DescType dType, AEDesc *desc)
  93. {
  94.     desc->descriptorType = dType;
  95.     (void) PtrToHand(&value, &desc->dataHandle, sizeof(value));
  96. } /* DescTypeToDesc() */
  97.  
  98. /*
  99.  * LongToDesc() -- 
  100.  *    Put a longint into a descriptor record.
  101.  */
  102. void LongToDesc(long value, DescType dType, AEDesc *desc)
  103. {
  104.     desc->descriptorType = dType;
  105.     if (dType == typeLongDateTime)
  106.     {
  107.         desc->dataHandle = NewHandle(8);
  108.         *(long *) *desc->dataHandle = 0;
  109.         *(long *) (*desc->dataHandle + 4) = value;
  110.     }
  111.     else
  112.         (void) PtrToHand(&value, &desc->dataHandle, sizeof(value));
  113. } /* LongToDesc() */
  114.  
  115. /*
  116.  * FSSpecToDesc() -- 
  117.  *    Put a File System Spec into a descriptor record.
  118.  */
  119. void FSSpecToDesc(FSSpec *valuep, DescType dType, AEDesc *desc)
  120. {
  121.     OSErr    osstat;
  122.     
  123.     desc->descriptorType = dType;
  124.     if (dType == typeFSS)
  125.         (void) PtrToHand(valuep, &desc->dataHandle, sizeof(FSSpec));
  126.     else if (dType == typeAlias)
  127.     {
  128.         osstat = NewAlias(nil, valuep, (AliasHandle *) &desc->dataHandle);
  129.         if (osstat != noErr)
  130.             InitDesc(desc);
  131.     }
  132.     else
  133.         InitDesc(desc);
  134. } /* FSSpecToDesc() */
  135.  
  136. /*
  137.  * findProcessBySignature() -- 
  138.  *    Find a running process based on its signature
  139.  *    See IM-VI 29-11 
  140.  */
  141. Boolean findProcessBySignature(OSType sig, ProcessSerialNumber *psn_p, long *proc_mode_p)
  142. {
  143.     ProcessInfoRec        procInfo;
  144.  
  145.     psn_p->highLongOfPSN = 0;
  146.     psn_p->lowLongOfPSN = kNoProcess;
  147.     
  148.     procInfo.processInfoLength = sizeof(procInfo);
  149.     procInfo.processName = NULL;
  150.     procInfo.processAppSpec = NULL;
  151.     
  152.     while (GetNextProcess(psn_p) == noErr)
  153.         if (GetProcessInformation(psn_p, &procInfo) == noErr)
  154.             if ((procInfo.processType == 'APPL') &&
  155.                 (procInfo.processSignature == sig))
  156.             {
  157.                 *proc_mode_p = procInfo.processMode;
  158.                 return true;
  159.             }
  160.                 
  161.     return false;
  162. } /* findProcessBySignature() */
  163.  
  164. /*
  165.  * findAppBySignature() -- 
  166.  *    Use the desktop database to find an app with this sig on a mounted volume.
  167.  */
  168. Boolean findAppBySignature(OSType sig, FSSpec *fspec_p)
  169. {
  170.     ParamBlockRec        pb;
  171.     HParamBlockRec        hpb;
  172.     GetVolParmsInfoBuffer    volParms;
  173.     DTPBRec            dtpb;
  174.     OSErr            osstat;
  175.  
  176.     /* for each volume */
  177.     pb.volumeParam.ioCompletion = NULL;
  178.     pb.volumeParam.ioNamePtr = NULL;
  179.     pb.volumeParam.ioVRefNum = 0;
  180.     pb.volumeParam.ioVolIndex = 1;
  181.     osstat = PBGetVInfo(&pb, false);
  182.     while (osstat == noErr)
  183.     {
  184.         /* check to see if it supports the desktop manager */
  185.         hpb.ioParam.ioCompletion = NULL;
  186.         hpb.ioParam.ioVRefNum = pb.volumeParam.ioVRefNum;
  187.         hpb.ioParam.ioNamePtr = NULL;
  188.         hpb.ioParam.ioBuffer = (Ptr) &volParms;
  189.         hpb.ioParam.ioReqCount = sizeof(volParms);
  190.         osstat = PBHGetVolParms(&hpb, false);
  191.         if ((osstat == noErr) && (volParms.vMAttrib & (1 << bHasDesktopMgr)))
  192.         {
  193.             /* find out the Desktop reference number */
  194.             dtpb.ioNamePtr = NULL;
  195.             dtpb.ioVRefNum = pb.volumeParam.ioVRefNum;
  196.             osstat = PBDTGetPath(&dtpb);
  197.             if (osstat == noErr)
  198.             {
  199.                 /* search this Desktop database for an app with the right signature */
  200.                 dtpb.ioCompletion = NULL;
  201.                 dtpb.ioNamePtr = (StringPtr) &(fspec_p->name);
  202.                 dtpb.ioIndex = 0;
  203.                 dtpb.ioFileCreator = sig;
  204.                 osstat = PBDTGetAPPL(&dtpb, false);
  205.                 if (osstat == noErr)
  206.                 {
  207.                     /* found the app */
  208.                     fspec_p->vRefNum = pb.volumeParam.ioVRefNum;
  209.                     fspec_p->parID = dtpb.ioAPPLParID;
  210.                     return true;
  211.                 } /* PBDTGetAPPL == noErr */
  212.             } /* PBDTGetPath == noErr */
  213.         } /* PBHGetVolParms == noErr */
  214.     
  215.         pb.volumeParam.ioVolIndex++;
  216.         osstat = PBGetVInfo(&pb, false);
  217.     } /* while PBGetVInfo == noErr */
  218.     
  219.     return false;
  220. } /* findAppBySignature() */
  221.  
  222. /*
  223.  * InitAEToApp() -- 
  224.  *    Initialize an apple event to be sent to an application.  Return the event, and
  225.  *    whether the application is currently running.
  226.  */
  227. OSErr InitAEToApp(OSType appSig, AEEventClass eventClass, AEEventID eventID, 
  228.             AppleEvent *aevt, Boolean *running)
  229. {
  230.     AEDesc            addrDesc;
  231.     ProcessSerialNumber    psn;
  232.     long            dummy;
  233.     OSErr            osstat;
  234.  
  235.     InitDesc(&addrDesc);
  236.     osstat = noErr;
  237.     
  238.     *running = findProcessBySignature(appSig, &psn, &dummy);
  239.     if (*running)
  240.         osstat = AECreateDesc(typeProcessSerialNumber, &psn, sizeof(psn), &addrDesc);
  241.     else
  242.         osstat = AECreateDesc(typeApplSignature, &appSig, sizeof(OSType), &addrDesc);
  243.     if (osstat != noErr) 
  244.         goto exit;
  245.     
  246.     osstat = AECreateAppleEvent(eventClass, eventID, &addrDesc, 
  247.                 kAutoGenerateReturnID, kAnyTransactionID,
  248.                 aevt);
  249. exit:
  250.     DisposeDesc(&addrDesc);
  251.     return osstat;
  252. } /* InitAEToApp() */
  253.  
  254. /*
  255.  * SendAEToApp() --
  256.  *    Send an Apple Event to an application, which may or may not be running.  If it isn't
  257.  *    running, the event reply won't be filled in....
  258.  */
  259. OSErr SendAEToApp(OSType appSig, AppleEvent *aevt, AppleEvent *aereply, AEIdleUPP idleUPP, Boolean running)
  260. {
  261.     LaunchParamBlockRec    lpb;
  262.     AEDesc            appParmDesc;
  263.     AEDesc            replyDesc;
  264.     AppleEvent        myreply;
  265.     AppleEvent        *replyp;
  266.     FSSpec            appFspec;
  267.     OSErr            osstat = noErr;
  268.     
  269.     InitDesc(&appParmDesc);
  270.     InitDesc(&myreply);
  271.     InitDesc(&replyDesc);
  272.     
  273.     if (running)
  274.     {
  275.         /* the app is running, just send the event */
  276.         replyp = aereply ? aereply : &myreply;
  277.         osstat = AESend(aevt, replyp, kAEWaitReply + kAECanInteract + kAECanSwitchLayer + kAEDontReconnect,
  278.                 kAENormalPriority, kAEDefaultTimeout, idleUPP, nil);
  279.         if (osstat == -603)
  280.             /* ignore this error, it doesn't seem to matter */
  281.             osstat = noErr;
  282.         if (osstat == noErr)
  283.         {
  284.             osstat = AEGetParamDesc(replyp, keyErrorNumber, typeLongInteger, &replyDesc);
  285.             if (osstat == noErr)
  286.                 osstat = **(long **) replyDesc.dataHandle;
  287.             else if (osstat == errAEDescNotFound)
  288.                 /* no error code, no error */
  289.                 osstat = noErr;
  290.         }
  291.     } // running
  292.     else if (findAppBySignature(appSig, &appFspec))
  293.     {
  294.         /* we need to launch the app with the event */
  295.         osstat = AECoerceDesc(aevt, typeAppParameters, &appParmDesc);
  296.         if (osstat != noErr)
  297.             goto exit;
  298.         
  299.         HLock(appParmDesc.dataHandle);
  300.         
  301.         /* call LaunchApplication */
  302.         lpb.launchBlockID = extendedBlock;
  303.         lpb.launchEPBLength = extendedBlockLen;
  304.         lpb.launchFileFlags = launchNoFileFlags;
  305.         lpb.launchControlFlags = launchContinue + launchDontSwitch;
  306.         lpb.launchAppSpec = &appFspec;
  307.         lpb.launchAppParameters = (AppParametersPtr) *appParmDesc.dataHandle;
  308.         THz    oldZone = GetZone();
  309.         osstat = LaunchApplication(&lpb);
  310.         if (osstat == -603)
  311.             /* ignore this error, it doesn't seem to matter */
  312.             osstat = noErr;
  313.         SetZone(oldZone);
  314.     } // findAppBySignature()
  315.     else
  316.         /* app can't be found */
  317.         osstat = fnfErr;
  318.  
  319. exit:
  320.     DisposeDesc(&appParmDesc);
  321.     DisposeDesc(&myreply);
  322.     DisposeDesc(&replyDesc);
  323.     return osstat;
  324. } /* SendAEToApp() */
  325.  
  326. /*
  327.  * SendDirectAppleEvent() -- 
  328.  *    Send a simple event w/ just a direct parameter.
  329.  */
  330. OSErr SendDirectAppleEvent(OSType appSig, AEEventClass eventClass, AEEventID eventID,
  331.                 AEDesc *directDesc, AppleEvent *aereply, AEIdleUPP idleUPP)
  332. {
  333.     AppleEvent    aevt;
  334.     OSErr        osstat;
  335.     Boolean        running;
  336.  
  337.     InitDesc(&aevt);
  338.     osstat = noErr;
  339.     
  340.     /* create the event */
  341.     osstat = InitAEToApp(appSig, eventClass, eventID, &aevt, &running);
  342.     if (osstat != noErr) 
  343.         goto exit;
  344.         
  345.     /* add direct object */
  346.     osstat = AEPutParamDesc(&aevt, keyDirectObject, directDesc);
  347.     if (osstat != noErr) 
  348.         goto exit;
  349.         
  350.     /* send the event */
  351.     osstat = SendAEToApp(appSig, &aevt, aereply, idleUPP, running);
  352.     
  353. exit:
  354.     DisposeDesc(&aevt);
  355.     return osstat;
  356. } /* SendDirectAppleEvent */
  357.  
  358. /*
  359.  * SendDirectAppleEventWithArg() -- 
  360.  *    Send a simple event w/ a direct parameter and one other argument.
  361.  */
  362. OSErr SendDirectAppleEventWithArg(OSType appSig, AEEventClass eventClass, AEEventID eventID,
  363.                 AEDesc *directDesc, AEKeyword argKey, AEDesc *argDesc,
  364.                 AppleEvent *aereply, AEIdleUPP idleUPP)
  365. {
  366.     AppleEvent    aevt;
  367.     OSErr        osstat;
  368.     Boolean        running;
  369.  
  370.     InitDesc(&aevt);
  371.     osstat = noErr;
  372.     
  373.     /* create the event */
  374.     osstat = InitAEToApp(appSig, eventClass, eventID, &aevt, &running);
  375.     if (osstat != noErr) 
  376.         goto exit;
  377.         
  378.     /* add direct object */
  379.     osstat = AEPutParamDesc(&aevt, keyDirectObject, directDesc);
  380.     if (osstat != noErr) 
  381.         goto exit;
  382.         
  383.     /* add argument */
  384.     osstat = AEPutParamDesc(&aevt, argKey, argDesc);
  385.     if (osstat != noErr) 
  386.         goto exit;
  387.         
  388.     /* send the event */
  389.     osstat = SendAEToApp(appSig, &aevt, aereply, idleUPP, running);
  390.     
  391. exit:
  392.     DisposeDesc(&aevt);
  393.     return osstat;
  394. } /* SendDirectAppleEventWithArg */
  395.  
  396. /*
  397.  * SendDirectAppleEventWithThreeArgs() -- 
  398.  *    Send ourselves an event w/ a direct parameter and three other arguments.
  399.  */
  400. OSErr SendDirectAppleEventWithThreeArgs(OSType appSig, AEEventClass eventClass, AEEventID eventID,
  401.                 AEDesc *directDesc, AEKeyword argKey, AEDesc *argDesc,
  402.                 AEKeyword arg2Key, AEDesc *arg2Desc,
  403.                 AEKeyword arg3Key, AEDesc *arg3Desc,
  404.                 AppleEvent *aereply, AEIdleUPP idleUPP)
  405. {
  406.     AppleEvent    aevt;
  407.     OSErr        osstat;
  408.     Boolean        running;
  409.  
  410.     InitDesc(&aevt);
  411.     osstat = noErr;
  412.     
  413.     /* create the event */
  414.     osstat = InitAEToApp(appSig, eventClass, eventID, &aevt, &running);
  415.     if (osstat != noErr) 
  416.         goto exit;
  417.         
  418.     /* add direct object */
  419.     osstat = AEPutParamDesc(&aevt, keyDirectObject, directDesc);
  420.     if (osstat != noErr) 
  421.         goto exit;
  422.         
  423.     /* add arguments */
  424.     osstat = AEPutParamDesc(&aevt, argKey, argDesc);
  425.     if (osstat != noErr) 
  426.         goto exit;
  427.     osstat = AEPutParamDesc(&aevt, arg2Key, arg2Desc);
  428.     if (osstat != noErr) 
  429.         goto exit;
  430.     osstat = AEPutParamDesc(&aevt, arg3Key, arg3Desc);
  431.     if (osstat != noErr) 
  432.         goto exit;
  433.                 
  434.     /* send the event */
  435.     osstat = SendAEToApp(appSig, &aevt, aereply, idleUPP, running);
  436.     
  437. exit:
  438.     DisposeDesc(&aevt);
  439.     return osstat;
  440. } /* SendDirectAppleEventWithThreeArgs */
  441.  
  442. /*
  443.  * SendCreateAppleEvent() -- 
  444.  *    Send a Create Element event.
  445.  */
  446. OSErr SendCreateAppleEvent(OSType appSig, DescType objClass, AEDesc *insertLocDesc,
  447.                 AEDesc *dataDesc, AEDesc *propDesc, 
  448.                 AppleEvent *aereply, AEIdleUPP idleUPP)
  449. {
  450.     AppleEvent    aevt;
  451.     OSErr        osstat;
  452.     Boolean        running;
  453.  
  454.     InitDesc(&aevt);
  455.     osstat = noErr;
  456.     
  457.     /* create the event */
  458.     osstat = InitAEToApp(appSig, kAECoreSuite, kAECreateElement, &aevt, &running);
  459.     if (osstat != noErr) 
  460.         goto exit;
  461.         
  462.     /* add desired class */
  463.     osstat = AEPutParamPtr(&aevt, keyAEObjectClass, typeType, &objClass, 
  464.                             sizeof(objClass));
  465.     if (osstat != noErr)
  466.         goto exit;
  467.         
  468.     /* add insertion location */
  469.     osstat = AEPutParamDesc(&aevt, keyAEInsertHere, insertLocDesc);
  470.     if (osstat != noErr) 
  471.         goto exit;
  472.         
  473.     /* add initial data, if (there is some */
  474.     if (dataDesc && (dataDesc->descriptorType != typeNull))
  475.     {
  476.         osstat = AEPutParamDesc(&aevt, keyAEData, dataDesc);
  477.         if (osstat != noErr)
  478.             goto exit;
  479.     }
  480.     
  481.     /* add initial property values, if (there are some */
  482.     if (propDesc && (propDesc->descriptorType != typeNull))
  483.     {
  484.         osstat = AEPutParamDesc(&aevt, keyAEPropData, propDesc);
  485.         if (osstat != noErr)
  486.             goto exit;
  487.     }
  488.     
  489.     /* send the event */
  490.     osstat = SendAEToApp(appSig, &aevt, aereply, idleUPP, running);
  491.     
  492. exit:
  493.     DisposeDesc(&aevt);
  494.     return osstat;
  495. } /* SendCreateAppleEvent() */
  496.  
  497. /*
  498.  * SendMoveCloneAppleEvent() -- 
  499.  *    Send a Move or Clone event.
  500.  */
  501. OSErr SendMoveCloneAppleEvent(OSType appSig, AEEventID eventID, AEDesc *directDesc, 
  502.                 AEDesc *insertLocDesc, AppleEvent *aereply, AEIdleUPP idleUPP)
  503. {
  504.     AppleEvent    aevt;
  505.     OSErr        osstat;
  506.     Boolean        running;
  507.  
  508.     InitDesc(&aevt);
  509.     osstat = noErr;
  510.     
  511.     /* create the event */
  512.     osstat = InitAEToApp(appSig, kAECoreSuite, eventID, &aevt, &running);
  513.     if (osstat != noErr) 
  514.         goto exit;
  515.         
  516.     /* add direct object */
  517.     osstat = AEPutParamDesc(&aevt, keyDirectObject, directDesc);
  518.     if (osstat != noErr) 
  519.         goto exit;
  520.         
  521.     /* add insertion location */
  522.     osstat = AEPutParamDesc(&aevt, keyAEInsertHere, insertLocDesc);
  523.     if (osstat != noErr) 
  524.         goto exit;
  525.         
  526.     /* send the event */
  527.     osstat = SendAEToApp(appSig, &aevt, aereply, idleUPP, running);
  528.     
  529. exit:
  530.     DisposeDesc(&aevt);
  531.     return osstat;
  532. } /* SendMoveCloneAppleEvent() */
  533.  
  534. /* 
  535.  * CreateFormNameOSpec() --
  536.  *    Create a formName object specifier.
  537.  */
  538. OSErr CreateFormNameOSpec(char *name, DescType objClass, AEDesc *containerDesc, AEDesc *ospecDesc)
  539. {
  540.     AEDesc    keyDesc;
  541.     AEDesc    nullDesc;
  542.     
  543.     InitDesc(&keyDesc);
  544.     InitDesc(&nullDesc);
  545.     CStringToDesc(name, typeChar, &keyDesc);
  546.     OSErr    osstat = CreateObjSpecifier(objClass, containerDesc ? containerDesc : &nullDesc, 
  547.                         formName, &keyDesc, false, ospecDesc);
  548.     DisposeDesc(&keyDesc);
  549.     return osstat;
  550. } // CreateFormNameOSpec()
  551.  
  552. /* 
  553.  * CreatePropertyOSpec() --
  554.  *    Create a formPropertyID object specifier.
  555.  */
  556. OSErr CreatePropertyOSpec(DescType propCode, AEDesc *containerDesc, AEDesc *ospecDesc)
  557. {
  558.     AEDesc    keyDesc;
  559.     AEDesc    nullDesc;
  560.     
  561.     InitDesc(&keyDesc);
  562.     InitDesc(&nullDesc);
  563.     DescTypeToDesc(propCode, typeType, &keyDesc);
  564.     OSErr    osstat = CreateObjSpecifier(cProperty, containerDesc ? containerDesc : &nullDesc, 
  565.                         formPropertyID, &keyDesc, false, ospecDesc);
  566.     DisposeDesc(&keyDesc);
  567.     return osstat;
  568. } // CreatePropertyOSpec()
  569.  
  570. /*
  571.  * FetchOpenURL() --
  572.  *    Tell Fetch to open a directory (specified by a URL).
  573.  */
  574. OSErr FetchOpenURL(char *url, AEIdleUPP idleUPP)
  575. {
  576.     AEDesc    urlDesc;
  577.     OSErr    osstat = noErr;
  578.     
  579.     InitDesc(&urlDesc);
  580.     osstat = CreateFormNameOSpec(url, cURL, nil, &urlDesc);
  581.     if (osstat == noErr)
  582.         osstat = SendDirectAppleEvent(FETCH_APP_SIGNATURE, kCoreEventClass, kAEOpen, &urlDesc,
  583.                         nil, idleUPP);
  584.     DisposeDesc(&urlDesc);
  585.     return osstat;
  586. } // FetchOpenURL()
  587.  
  588.  
  589. /*
  590.  * FetchPut() --
  591.  *    Tell Fetch to upload a file or folder to a URL
  592.  */
  593. OSErr FetchPut(FSSpec *fspec, char *url, AEIdleUPP idleUPP)
  594. {
  595.     AEDesc    urlDesc;
  596.     AEDesc    fspecDesc;
  597.     OSErr    osstat = noErr;
  598.     
  599.     InitDesc(&urlDesc);
  600.     InitDesc(&fspecDesc);
  601.     
  602.     osstat = CreateFormNameOSpec(url, cURL, nil, &urlDesc);
  603.     if (osstat != noErr)
  604.         goto exit;
  605.     FSSpecToDesc(fspec, typeAlias, &fspecDesc);
  606.     
  607.     osstat = SendDirectAppleEventWithArg(FETCH_APP_SIGNATURE, kAEFetchSuite, kAEPutIntoEvent, 
  608.                             &urlDesc,
  609.                             kAEFetchPutIntoItemsParam, &fspecDesc,
  610.                             nil, idleUPP);
  611. exit:
  612.     DisposeDesc(&urlDesc);
  613.     DisposeDesc(&fspecDesc);
  614.     return osstat;
  615. } // FetchPut()
  616.  
  617. /*
  618.  * FetchGet() --
  619.  *    Tell Fetch to download a file or folder from a URL to a folder
  620.  */
  621. OSErr FetchGet(char *url, FSSpec *fspec, AEIdleUPP idleUPP)
  622. {
  623.     AEDesc        nullDesc;
  624.     AEDesc        aerDesc;
  625.     AEDesc        insertLocDesc;
  626.     AEDesc        fspecDesc;
  627.     AEDesc        urlDesc;
  628.     DescType    positionCode;
  629.     OSErr        osstat;
  630.  
  631.     InitDesc(&nullDesc);
  632.     InitDesc(&aerDesc);
  633.     InitDesc(&insertLocDesc);
  634.     InitDesc(&fspecDesc);
  635.     InitDesc(&urlDesc);
  636.     osstat = noErr;
  637.     
  638.     /* first get Ospec for target folder */
  639.     FSSpecToDesc(fspec, typeAlias, &fspecDesc);
  640.     
  641.     /* next build insertion location ("Beginning of alias foo") */
  642.     osstat = AECreateList(nil, 0, true, &aerDesc);
  643.     if (osstat != noErr)
  644.         goto exit;
  645.         
  646.     /* add object-in-relation-to field */
  647.     osstat = AEPutKeyDesc(&aerDesc, keyAEObject, &fspecDesc);
  648.     if (osstat != noErr)
  649.         goto exit;
  650.         
  651.     /* add positioning field */
  652.     positionCode = kAEBeginning;
  653.     osstat = AEPutKeyPtr(&aerDesc, keyAEPosition, typeEnumerated, &positionCode,
  654.                 sizeof(positionCode));
  655.     if (osstat != noErr)
  656.         goto exit;
  657.         
  658.     /* coerce to typeInsertionLoc */
  659.     osstat = AECoerceDesc(&aerDesc, typeInsertionLoc, &insertLocDesc);
  660.     if (osstat != noErr)
  661.         goto exit;
  662.         
  663.     /* create Ospec for item to get */
  664.     osstat = CreateFormNameOSpec(url, cURL, nil, &urlDesc);
  665.     if (osstat != noErr)
  666.         goto exit;
  667.         
  668.     /* now send the event */
  669.     osstat = SendMoveCloneAppleEvent(FETCH_APP_SIGNATURE, kAEClone, &urlDesc, 
  670.                         &insertLocDesc, nil, idleUPP);
  671.     
  672. exit:    /* clean up */
  673.     DisposeDesc(&nullDesc);
  674.     DisposeDesc(&aerDesc);
  675.     DisposeDesc(&insertLocDesc);
  676.     DisposeDesc(&urlDesc);
  677.     DisposeDesc(&fspecDesc);
  678.     return osstat;
  679. } // FetchGet()
  680.  
  681. /*
  682.  * FetchViewFile() --
  683.  *    Tell Fetch to view a file (specified by a URL).
  684.  */
  685. OSErr FetchViewFile(char *url, AEIdleUPP idleUPP)
  686. {
  687.     AEDesc    urlDesc;
  688.     OSErr    osstat = noErr;
  689.     
  690.     InitDesc(&urlDesc);
  691.     osstat = CreateFormNameOSpec(url, cURL, nil, &urlDesc);
  692.     if (osstat == noErr)
  693.         osstat = SendDirectAppleEvent(FETCH_APP_SIGNATURE, kAEFetchSuite, kAEViewFileEvent, 
  694.                         &urlDesc, nil, idleUPP);
  695.     DisposeDesc(&urlDesc);
  696.     return osstat;
  697. } // FetchViewFile()
  698.  
  699. /*
  700.  * FetchItemExists() --
  701.  *    Ask Fetch whether a file (or directory) is included in the frontmost transfer window file list.
  702.  */
  703. OSErr FetchItemExists(char *fname, Boolean *exists, AEIdleUPP idleUPP)
  704. {
  705.     AppleEvent    aereply;
  706.     AEDesc        fnameDesc;
  707.     AEDesc        replyDesc;
  708.     OSErr        osstat = noErr;
  709.     
  710.     InitDesc(&aereply);
  711.     InitDesc(&fnameDesc);
  712.     InitDesc(&replyDesc);
  713.     
  714.     osstat = CreateFormNameOSpec(fname, cHostItem, nil, &fnameDesc);
  715.     if (osstat != noErr)
  716.         goto exit;
  717.     
  718.     osstat = SendDirectAppleEvent(FETCH_APP_SIGNATURE, kAECoreSuite, kAEDoObjectsExist, 
  719.                         &fnameDesc, &aereply, idleUPP);
  720.     if (osstat != noErr)
  721.         goto exit;
  722.         
  723.     osstat = AEGetParamDesc(&aereply, keyAEResult, typeBoolean, &replyDesc);
  724.     if (osstat != noErr)
  725.         goto exit;
  726.     
  727.     *exists = **replyDesc.dataHandle != 0;
  728.     
  729. exit:
  730.     DisposeDesc(&aereply);
  731.     DisposeDesc(&fnameDesc);
  732.     DisposeDesc(&replyDesc);
  733.     return osstat;
  734. } // FetchItemExists()
  735.  
  736. /*
  737.  * FetchRenameItem() --
  738.  *    Rename an item in the frontmost transfer window file list.
  739.  */
  740. OSErr FetchRenameItem(char *oldname, char *newname, AEIdleUPP idleUPP)
  741. {
  742.     AEDesc        itemDesc;
  743.     AEDesc        propDesc;
  744.     AEDesc        newnameDesc;
  745.     OSErr        osstat = noErr;
  746.     
  747.     InitDesc(&itemDesc);
  748.     InitDesc(&propDesc);
  749.     InitDesc(&newnameDesc);
  750.     
  751.     /* create ospec for name of named item */
  752.     osstat = CreateFormNameOSpec(oldname, cHostItem, nil, &itemDesc);
  753.     if (osstat != noErr)
  754.         goto exit;
  755.         
  756.     osstat = CreatePropertyOSpec(pName, &itemDesc, &propDesc);
  757.     if (osstat != noErr)
  758.         goto exit;
  759.         
  760.     /* create desc for new name */
  761.     CStringToDesc(newname, typeChar, &newnameDesc);
  762.     
  763.     /* send the event */
  764.     osstat = SendDirectAppleEventWithArg(FETCH_APP_SIGNATURE, kAECoreSuite, kAESetData, 
  765.                         &propDesc, keyAEData, &newnameDesc, nil, idleUPP);
  766.     if (osstat != noErr)
  767.         goto exit;
  768.     
  769. exit:
  770.     DisposeDesc(&itemDesc);
  771.     DisposeDesc(&propDesc);
  772.     DisposeDesc(&newnameDesc);
  773.     return osstat;
  774. } // FetchRenameItem()
  775.  
  776. /*
  777.  * FetchCreateDirectory() --
  778.  *    Tell Fetch to create a directory (in the frontmost transfer window).
  779.  */
  780. OSErr FetchCreateDirectory(char *dirname, AEIdleUPP idleUPP)
  781. {
  782.     AEDesc        nullDesc;
  783.     AEDesc        aerDesc;
  784.     AEDesc        insertLocDesc;
  785.     AEDesc        propDesc;
  786.     DescType    positionCode;
  787.     OSErr        osstat;
  788.  
  789.     InitDesc(&nullDesc);
  790.     InitDesc(&aerDesc);
  791.     InitDesc(&insertLocDesc);
  792.     InitDesc(&propDesc);
  793.     osstat = noErr;
  794.     
  795.     /* first build insertion location ("Beginning of null container") */
  796.     /* NOTE: null container equals the front window in this case */
  797.     osstat = AECreateList(nil, 0, true, &aerDesc);
  798.     if (osstat != noErr)
  799.         goto exit;
  800.         
  801.     /* add object-in-relation-to field */
  802.     osstat = AEPutKeyDesc(&aerDesc, keyAEObject, &nullDesc);
  803.     if (osstat != noErr)
  804.         goto exit;
  805.         
  806.     /* add positioning field */
  807.     positionCode = kAEBeginning;
  808.     osstat = AEPutKeyPtr(&aerDesc, keyAEPosition, typeEnumerated, &positionCode,
  809.                 sizeof(positionCode));
  810.     if (osstat != noErr)
  811.         goto exit;
  812.         
  813.     /* coerce to typeInsertionLoc */
  814.     osstat = AECoerceDesc(&aerDesc, typeInsertionLoc, &insertLocDesc);
  815.     if (osstat != noErr)
  816.         goto exit;
  817.         
  818.     /* build initial property data */
  819.     osstat = AECreateList(nil, 0, true, &propDesc);
  820.     if (osstat != noErr)
  821.         goto exit;
  822.             
  823.     /* add dir name (can't create dir without it) */
  824.     osstat = AEPutKeyPtr(&propDesc, pName, typeChar, dirname, strlen(dirname));
  825.     if (osstat != noErr)
  826.         goto exit;
  827.  
  828.     /* now send the event */
  829.     osstat = SendCreateAppleEvent(FETCH_APP_SIGNATURE, cHostDirectory, 
  830.                         &insertLocDesc, nil, &propDesc, nil, idleUPP);
  831.     
  832. exit:    /* clean up */
  833.     DisposeDesc(&nullDesc);
  834.     DisposeDesc(&aerDesc);
  835.     DisposeDesc(&insertLocDesc);
  836.     DisposeDesc(&propDesc);
  837.     return osstat;
  838. } // FetchCreateDirectory()
  839.  
  840. /*
  841.  * FetchSendCommand() --
  842.  *    Tell Fetch to send a custom command (or CR-delimited list of commands)
  843.  *    to a URL (i.e. connect to the URL, then send the commands).
  844.  */
  845. OSErr FetchSendCommand(char *cmd, char *url, AEIdleUPP idleUPP)
  846. {
  847.     AEDesc    urlDesc;
  848.     AEDesc    cmdDesc;
  849.     OSErr    osstat = noErr;
  850.     
  851.     InitDesc(&urlDesc);
  852.     InitDesc(&cmdDesc);
  853.     
  854.     osstat = CreateFormNameOSpec(url, cURL, nil, &urlDesc);
  855.     if (osstat != noErr)
  856.         goto exit;
  857.     CStringToDesc(cmd, typeChar, &cmdDesc);
  858.     
  859.     osstat = SendDirectAppleEventWithArg(FETCH_APP_SIGNATURE, kAEFetchSuite, kAESendFTPCommandEvent, 
  860.                             &urlDesc,
  861.                             kAEFetchSendFTPCommandsParam, &cmdDesc,
  862.                             nil, idleUPP);
  863. exit:
  864.     DisposeDesc(&urlDesc);
  865.     DisposeDesc(&cmdDesc);
  866.     return osstat;
  867. } // FetchSendCommand()
  868.  
  869. /*
  870.  * FetchGetPreference() --
  871.  *    Get an arbitrary Fetch preference.
  872.  */
  873. OSErr FetchGetPreference(DescType propCode, AEDesc *valueDesc, AEIdleUPP idleUPP)
  874. {
  875.     AppleEvent    aereply;
  876.     AEDesc        nullDesc;
  877.     AEDesc        propDesc;
  878.     OSErr        osstat = noErr;
  879.     
  880.     InitDesc(&aereply);
  881.     InitDesc(&nullDesc);
  882.     InitDesc(&propDesc);
  883.     
  884.     /* create ospec for application object property (app object == null) */
  885.     osstat = CreatePropertyOSpec(propCode, &nullDesc, &propDesc);
  886.     if (osstat != noErr)
  887.         goto exit;
  888.         
  889.     /* send the event */
  890.     osstat = SendDirectAppleEvent(FETCH_APP_SIGNATURE, kAECoreSuite, kAEGetData, 
  891.                         &propDesc, &aereply, idleUPP);
  892.     if (osstat != noErr)
  893.         goto exit;
  894.         
  895.     osstat = AEGetParamDesc(&aereply, keyAEResult, typeWildCard, valueDesc);
  896.     if (osstat != noErr)
  897.         goto exit;
  898.         
  899. exit:
  900.     DisposeDesc(&aereply);
  901.     DisposeDesc(&nullDesc);
  902.     DisposeDesc(&propDesc);
  903.     return osstat;
  904. } // FetchGetPreference()
  905.  
  906. /*
  907.  * FetchSetPreference() --
  908.  *    Set an arbitrary Fetch preference.
  909.  */
  910. OSErr FetchSetPreference(DescType propCode, AEDesc *valueDesc, AEIdleUPP idleUPP)
  911. {
  912.     AEDesc        nullDesc;
  913.     AEDesc        propDesc;
  914.     OSErr        osstat = noErr;
  915.     
  916.     InitDesc(&nullDesc);
  917.     InitDesc(&propDesc);
  918.     
  919.     /* create ospec for application object property (app object == null) */
  920.     osstat = CreatePropertyOSpec(propCode, &nullDesc, &propDesc);
  921.     if (osstat != noErr)
  922.         goto exit;
  923.         
  924.     /* send the event */
  925.     osstat = SendDirectAppleEventWithArg(FETCH_APP_SIGNATURE, kAECoreSuite, kAESetData, 
  926.                         &propDesc, keyAEData, valueDesc, nil, idleUPP);
  927.     if (osstat != noErr)
  928.         goto exit;
  929.     
  930. exit:
  931.     DisposeDesc(&nullDesc);
  932.     DisposeDesc(&propDesc);
  933.     return osstat;
  934. } // FetchSetPreference()
  935.  
  936.